1 package org.apache.lucene.index;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Random;
27
28 import org.apache.lucene.util.TestUtil;
29
30
31
32
33 public class MockRandomMergePolicy extends MergePolicy {
34 private final Random random;
35 boolean doNonBulkMerges = true;
36
37 public MockRandomMergePolicy(Random random) {
38
39
40 this.random = new Random(random.nextLong());
41 }
42
43
44
45
46
47 public void setDoNonBulkMerges(boolean v) {
48 doNonBulkMerges = v;
49 }
50
51 @Override
52 public MergeSpecification findMerges(MergeTrigger mergeTrigger, SegmentInfos segmentInfos, IndexWriter writer) {
53 MergeSpecification mergeSpec = null;
54
55
56 int numSegments = segmentInfos.size();
57
58 List<SegmentCommitInfo> segments = new ArrayList<>();
59 final Collection<SegmentCommitInfo> merging = writer.getMergingSegments();
60
61 for(SegmentCommitInfo sipc : segmentInfos) {
62 if (!merging.contains(sipc)) {
63 segments.add(sipc);
64 }
65 }
66
67 numSegments = segments.size();
68
69 if (numSegments > 1 && (numSegments > 30 || random.nextInt(5) == 3)) {
70
71 Collections.shuffle(segments, random);
72
73
74 mergeSpec = new MergeSpecification();
75 final int segsToMerge = TestUtil.nextInt(random, 1, numSegments);
76 if (doNonBulkMerges && random.nextBoolean()) {
77 mergeSpec.add(new MockRandomOneMerge(segments.subList(0, segsToMerge),random.nextLong()));
78 } else {
79 mergeSpec.add(new OneMerge(segments.subList(0, segsToMerge)));
80 }
81 }
82
83 return mergeSpec;
84 }
85
86 @Override
87 public MergeSpecification findForcedMerges(
88 SegmentInfos segmentInfos, int maxSegmentCount, Map<SegmentCommitInfo,Boolean> segmentsToMerge, IndexWriter writer)
89 throws IOException {
90
91 final List<SegmentCommitInfo> eligibleSegments = new ArrayList<>();
92 for(SegmentCommitInfo info : segmentInfos) {
93 if (segmentsToMerge.containsKey(info)) {
94 eligibleSegments.add(info);
95 }
96 }
97
98
99 MergeSpecification mergeSpec = null;
100 if (eligibleSegments.size() > 1 || (eligibleSegments.size() == 1 && isMerged(segmentInfos, eligibleSegments.get(0), writer) == false)) {
101 mergeSpec = new MergeSpecification();
102
103
104 Collections.shuffle(eligibleSegments, random);
105 int upto = 0;
106 while(upto < eligibleSegments.size()) {
107 int max = Math.min(10, eligibleSegments.size()-upto);
108 int inc = max <= 2 ? max : TestUtil.nextInt(random, 2, max);
109 if (doNonBulkMerges && random.nextBoolean()) {
110 mergeSpec.add(new MockRandomOneMerge(eligibleSegments.subList(upto, upto+inc), random.nextLong()));
111 } else {
112 mergeSpec.add(new OneMerge(eligibleSegments.subList(upto, upto+inc)));
113 }
114 upto += inc;
115 }
116 }
117
118 if (mergeSpec != null) {
119 for(OneMerge merge : mergeSpec.merges) {
120 for(SegmentCommitInfo info : merge.segments) {
121 assert segmentsToMerge.containsKey(info);
122 }
123 }
124 }
125 return mergeSpec;
126 }
127
128 @Override
129 public MergeSpecification findForcedDeletesMerges(SegmentInfos segmentInfos, IndexWriter writer) throws IOException {
130 return findMerges(null, segmentInfos, writer);
131 }
132
133 @Override
134 public boolean useCompoundFile(SegmentInfos infos, SegmentCommitInfo mergedInfo, IndexWriter writer) throws IOException {
135
136 return random.nextInt(5) != 1;
137 }
138
139 static class MockRandomOneMerge extends OneMerge {
140 final Random r;
141 ArrayList<CodecReader> readers;
142
143 MockRandomOneMerge(List<SegmentCommitInfo> segments, long seed) {
144 super(segments);
145 r = new Random(seed);
146 }
147
148 @Override
149 public List<CodecReader> getMergeReaders() throws IOException {
150 if (readers == null) {
151 readers = new ArrayList<CodecReader>(super.getMergeReaders());
152 for (int i = 0; i < readers.size(); i++) {
153
154
155
156 int thingToDo = r.nextInt(7);
157 if (thingToDo == 0) {
158
159 readers.set(i, SlowCodecReaderWrapper.wrap(new FilterLeafReader(readers.get(i))));
160 } else if (thingToDo == 1) {
161
162
163
164
165 readers.set(i, SlowCodecReaderWrapper.wrap(new MismatchedLeafReader(readers.get(i), r)));
166 }
167
168 }
169 }
170 return readers;
171 }
172 }
173 }